/*  This file is part of CASpp.

    CASpp is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    CASpp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with CASpp.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2014 Jérome LAURENS

    See https://code.google.com/p/idalgo/

*/

#ifndef CASPP_NODE_H
#define CASPP_NODE_H

#include "config.h"
#include "models.h"
#include "types.h"

CASPP_NS_BEGIN

#if 0
class Decimal;
class Complex;
class Root;
class Identifier;
class Symbol;
class Modulo;
class String;
class User;
class Map;
class GFX;
class EQW;
class Pointer;
class AlgExt;
class Polynomial;
class SparsePoly1;
#endif

CASPP_DECLARE_CLASS_REF(Node);
CASPP_DECLARE_TYPE_WRAP(Node);
CASPP_DECLARE_TYPE_WRAP(NodeRef);
CASPP_DECLARE_TYPE_WRAP(NodeConstRef);

NodeRef makeBooleanNodeRef(const std::string & s);
NodeRef makeStringNodeRef(const std::string & s);
NodeRef makeListNodeRef(const std::string &);
NodeRef makeVectorNodeRef(const std::string &);
NodeRef makeSetNodeRef(const std::string &);
NodeRef makeMapNodeRef(const std::string &);
NodeRef makeIntegerNodeRef(const std::string & s);
NodeRef makeRationalNodeRef(const std::string & s);
NodeRef makeRealNodeRef(const std::string & s);
NodeRef makeSymbolNodeRef(const std::string & s);
NodeRef makeVariableNodeRef(const std::string & s);
NodeRef makeFunctionNodeRef(const std::string & s);
NodeRef makeFunctionNodeRef(const SymbolRef & symbol, const ListRef & arguments);

NodeRef makeListNodeRef(const NodeRef & nRa, const NodeRef & nRb);
NodeRef makeVectorNodeRef(const NodeRef & nRa, const NodeRef &nRb);
NodeRef makeSetNodeRef(const NodeRef & nRa, const NodeRef &nRb);

class Node: public Agregate {
public:
    typedef Node __self;
    typedef Agregate __super;
    typedef Type::Unary type_t;
    typedef size_t line_t;
    typedef size_t column_t;

    class BadRef: public std::logic_error {
    public:
        typedef std::logic_error __super;
        BadRef();
    };

    Node();

    Node(const std::string & __new_x, type_t type); // pass Type::kAUTO as type to retrieve a number or string

    Node(const Boolean::Values __new_x);
    Node(const Boolean & __new_x);
    Node(const BooleanRef & __new_x);
    BooleanRef & booleanRef();
    const BooleanRef & booleanRef() const;
    bool isBoolean() const;

    Node(const String & __new_x);
    Node(const StringRef & __new_x);
    StringRef & stringRef();
    const StringRef & stringRef() const;
    bool isString() const;

    Node(const List & __new_x);
    Node(const ListRef & __new_x);
    ListRef & listRef();
    const ListRef & listRef() const;
    bool isList() const;

    Node(const Vector & __new_x);
    Node(const VectorRef & __new_x);
    VectorRef & vectorRef();
    const VectorRef & vectorRef() const;
    bool isVector() const;

    Node(const Set & __new_x);
    Node(const SetRef & __new_x);
    SetRef & setRef();
    const SetRef & setRef() const;
    bool isSet() const;

    Node(const Map & __new_x);
    Node(const MapRef & __new_x);
    MapRef & mapRef();
    const MapRef & mapRef() const;
    bool isMap() const;

    Node(const Integer & __new_x);
    Node(const IntegerRef & __new_x);
    IntegerRef & integerRef();
    const IntegerRef & integerRef() const;
    bool isInteger() const;

    Node(const Rational & __new_x);
    Node(const RationalRef & __new_x);
    RationalRef & rationalRef();
    const RationalRef & rationalRef() const;
    bool isRational() const;

    Node(const Real & __new_x);
    Node(const RealRef & __new_x);
    RealRef & realRef();
    const RealRef & realRef() const;
    bool isReal() const;

    Node(const Symbol & __new_x);
    Node(const SymbolRef & __new_x);
    SymbolRef & symbolRef();
    const SymbolRef & symbolRef() const;
    bool isSymbol() const;

    Node(const Variable & __new_x);
    Node(const VariableRef & __new_x);
    VariableRef & variableRef();
    const VariableRef & variableRef() const;
    bool isVariable() const;

    Node(const Function & __new_x);
    Node(const FunctionRef & __new_x);
    FunctionRef & functionRef();
    const FunctionRef & functionRef() const;
    bool isFunction() const;

    const std::string description() const;

    type_t type() const;
    std::string prettyType() const;

    bool isMutable() const;
    bool push_back(const NodeRef & n); // forwards to list, vector, set, function

    line_t line() const;
    void setLine(const line_t l);
    column_t column() const;
    void setColumn(const column_t c);

private:
    line_t line_m;
    column_t column_m;
};

CASPP_NS_END

#endif // CASPP_NODE_H
